<template>
  <div>

    <n-form
        ref="formRef"
        inline
        :label-width="80"
        :rules="rules"
        :model="props.paintEngineConfig"
    >
      <n-grid :cols="24" :x-gap="24">
        <n-form-item-gi :span="24" :show-label="false" v-if="props.model=='novel'">
          <n-button type="info" block @click="programmeShow = true"   >点击从方案库选取方案</n-button>
        </n-form-item-gi>
        <n-form-item-gi label="CHECKPOINT" path="defaultModel" :span="12">
          <n-select
              v-model:value="props.paintEngineConfig.defaultModel"
              :options="modelOption"
              :loading="resourceLoading"
              @update:value="changeModel"
              style="width: 100%"
          />
        </n-form-item-gi>
        <n-form-item-gi :span="12" label="VAE"  >
          <n-select
              :options="vaeOption"
              :loading="resourceLoading"
              v-model:value="props.paintEngineConfig.defaultVae"
              @update:value="changeVae"
              clearable
          />
        </n-form-item-gi>

        <n-form-item-gi :span="12" label="采样器" path="defaultSamplerName">
          <n-select
              :options="samperOptions" v-model:value="props.paintEngineConfig.defaultSamplerName" placeholder="请选择"
          />
        </n-form-item-gi>

        <n-form-item-gi :span="12" label="调度器" path="defaultScheduler">
          <n-select
              :options="schdulerOptions" v-model:value="props.paintEngineConfig.defaultScheduler" placeholder="请选择"
          />
        </n-form-item-gi>

        <n-form-item-gi :span="12" label="种子" path="defaultSeed">

          <n-input-number v-model:value="props.paintEngineConfig.defaultSeed" style="width: 100%"></n-input-number>
        </n-form-item-gi>

        <n-form-item-gi :span="12" label="提示词相关度" path="defaultCfgScale">
          <n-input-number style="width: 100%" :min="1" :max="10" v-model:value="props.paintEngineConfig.defaultCfgScale"/>
        </n-form-item-gi>

        <n-form-item-gi :span="12" label="批次数量" path="defaultBatchSize">
          <n-input-number style="width: 100%" :min="1" :max="4" v-model:value="props.paintEngineConfig.defaultBatchSize"/>
        </n-form-item-gi>

        <n-form-item-gi :span="12" label="采样迭代步数" path="defaultSteps">
          <n-input-number  style="width: 100%" :min="1" :max="60" v-model:value="props.paintEngineConfig.defaultSteps"/>
        </n-form-item-gi>


        <n-form-item-gi :span="8" label="尺寸设置">
          <n-select
            :options="imageSizeOption"
            v-model:value="props.paintEngineConfig.sizeOption"
            @update:value="setSizeOption"
            clearable
          />
        </n-form-item-gi>

        <n-form-item-gi :span="8" label="高度" path="height" >
          <n-input-number v-model:value="props.paintEngineConfig.defaultHeight" style="width: 100%; ">
            <template #prefix>
              高度
            </template>
          </n-input-number>
        </n-form-item-gi>

        <n-form-item-gi :span="8" label="宽度" path="width" >

          <n-input-number v-model:value="props.paintEngineConfig.defaultWidth" style="width: 100%;">
          </n-input-number>
        </n-form-item-gi>

        <n-form-item-gi :span="24" :show-label="false">
          <n-checkbox v-model:checked="props.paintEngineConfig.defaultRestoreFaces">
            脸部修复
          </n-checkbox>

          <n-checkbox v-model:checked="props.paintEngineConfig.defaultEnableHr">
            高清修复
          </n-checkbox>

          <n-checkbox v-if="props.model==='novel'" v-model:checked="props.paintEngineConfig.enableOpenPose">
            姿势图参考
          </n-checkbox>

          <n-checkbox v-if="props.model==='novel'"  v-model:checked="props.paintEngineConfig.enableReference">
            人物参考
          </n-checkbox>

<!--          <n-checkbox disabled v-if="props.model==='novel'"  v-model:checked="props.paintEngineConfig.enableRegionalPrompter">-->
<!--            多人插件-->
<!--          </n-checkbox>-->
        </n-form-item-gi>

        <n-form-item-gi :span="24" :show-label="false" v-if="props.paintEngineConfig.defaultEnableHr">
          <n-divider style="margin-top: 0;">高清修复选项</n-divider>
        </n-form-item-gi>

        <n-form-item-gi label-placement="left" label="放大算法" path="defaultHrUpscaler" :span="12"  v-if="props.paintEngineConfig.defaultEnableHr">
          <n-select v-model:value="props.paintEngineConfig.defaultHrUpscaler" :options="hrUpscalerOptions">
          </n-select>
        </n-form-item-gi>



        <n-form-item-gi label-placement="left" label="采样步数" :span="12"  v-if="props.paintEngineConfig.defaultEnableHr">
          <n-input-number style="width: 100%" v-model:value="props.paintEngineConfig.defaultHrSecondPassSteps" :min="1" :max="150"
                          :step="1"/>
        </n-form-item-gi>

        <n-form-item-gi label-placement="left"  label="重绘幅度" path="defaultDenoisingStrength" :span="12"  v-if="props.paintEngineConfig.defaultEnableHr">
          <n-input-number style="width: 100%" v-model:value="props.paintEngineConfig.defaultDenoisingStrength" :min="0" :max="1.0"
                          :step="0.01"/>
        </n-form-item-gi>

        <n-form-item-gi label-placement="left"  label="放大倍率" path="defaultHrScale" :span="12"  v-if="props.paintEngineConfig.defaultEnableHr">
          <n-input-number style="width: 100%" v-model:value="props.paintEngineConfig.defaultHrScale" :min="1" :max="4" :step="0.05"/>
        </n-form-item-gi>



        <n-card   :content-style="{padding: '10px 10px 10px 10px'}">
          <n-row>
            <n-col :span="13">
              <n-form-item v-if="props.paintEngineConfig.defaultEnableHr" label="方法算法" path="defaultHrUpscaler">
                <n-select v-model:value="props.paintEngineConfig.defaultHrUpscaler" :options="hrUpscalerOptions">
                </n-select>
              </n-form-item>
            </n-col>
            <n-col :span="1"></n-col>
            <n-col :span="10">
              <n-form-item v-if="props.paintEngineConfig.defaultEnableHr" label="采样步数" path="defaultHrSecondPassSteps">
                <n-input-number v-model:value="props.paintEngineConfig.defaultHrSecondPassSteps" :min="1" :max="150"
                                :step="1"/>
              </n-form-item>
            </n-col>
          </n-row>
          <n-row>
            <n-col :span="13">
              <n-form-item v-if="props.paintEngineConfig.defaultEnableHr" label="重绘幅度" path="defaultDenoisingStrength">
                <n-input-number v-model:value="props.paintEngineConfig.defaultDenoisingStrength" :min="0" :max="1.0"
                                :step="0.01"/>
              </n-form-item>
            </n-col>
            <n-col :span="1"></n-col>
            <n-col :span="10">
              <n-form-item v-if="props.paintEngineConfig.defaultEnableHr" label="放大倍率" path="defaultHrScale">
                <n-input-number v-model:value="props.paintEngineConfig.defaultHrScale" :min="1" :max="4" :step="0.05"/>
              </n-form-item>
            </n-col>
          </n-row>
        </n-card>

        <n-form-item-gi :span="24" label="预设正向提示词" path="defaultPrompt">
          <n-input v-model:value="props.paintEngineConfig.defaultPrompt" type="textarea" placeholder="请输入预设正向提示词"/>
        </n-form-item-gi>

        <n-form-item-gi :span="24" label="预设反向提示词" path="defaultNegativePrompt">
          <n-input v-model:value="props.paintEngineConfig.defaultNegativePrompt" type="textarea" placeholder="请输入预设正向提示词"/>
        </n-form-item-gi>

      </n-grid>
    </n-form>
    <n-tabs type="line" animated>
      <n-tab-pane name="Lora" tab="Lora模型" display-directive="show">
        <n-grid y-gap="5" x-gap="5" :cols="4">
          <n-gi v-if="loraList.length >0" v-for="lora in loraList">
            <n-card>
              <template #cover>
                <div class="image-container-lora" @contextmenu="handleContextMenu('lora', lora,$event)">
                  <n-image :src="fileFunction.getSDModelImage(lora.modelName,'lora')" class="centered-image-lora"/>
                </div>
              </template>
              <n-ellipsis style="width: 100%">
                {{ lora.modelName }}
              </n-ellipsis>
            </n-card>
          </n-gi>
        </n-grid>
      </n-tab-pane>
      <n-tab-pane name="T.I Embedding" tab="T.I Embedding" display-directive="show">
        <n-grid x-gap="12" :cols="8">
          <n-gi v-if="embeddingList.length >0" v-for="embedding in embeddingList">
            <n-card>
              <template #cover>
                <div class="image-container-lora"
                     @contextmenu="handleContextMenu('embedding' ,embedding, $event)">
                  <n-image :src="embedding.modelImage" class="centered-image-lora"/>
                </div>
              </template>
              <n-ellipsis style="width: 100%">
                {{ embedding.modelName }}
              </n-ellipsis>
            </n-card>
          </n-gi>
        </n-grid>
      </n-tab-pane>
    </n-tabs>

    <n-dropdown
        placement="bottom-start"
        trigger="manual"
        :x="x"
        :y="y"
        :options="loraSelectModelOption"
        :show="showDropdown"
        :on-clickoutside="clickOutSide"
        @select="handleSelect"
    />

    <n-drawer v-model:show="programmeShow" style="width: 1200px">
      <n-drawer-content title="StableDiffusion原创方案选择" closable>
        <ProgrammeSetting engineType="SD" programmeType="NOVEL" :choseConfig="choseProgrammeConfig"></ProgrammeSetting>
      </n-drawer-content>
    </n-drawer>

  </div>
</template>

<script setup lang="ts">
import {nextTick, onMounted, ref} from 'vue'
import {useMessage} from 'naive-ui'
import {resourceController} from '@/api/resource/resourceController.api'
// @ts-ignore
import fileFunction from "@/libs/globalFunction/file"
import {stableDiffusionDict} from '@/dictionary/stableDiffusionDict'
import ProgrammeSetting from "@/components/creator/boardConfig/programmeSetting.vue";

// 加载资源配置Loading
const resourceLoading = ref(false)
const selectedResource = ref("")
const modelOption = ref([])
const vaeOption = ref([])
const loraList = ref([])
const message = useMessage();
const taskStatus = ref("waiting");
const buttonLoading = ref(false)
const picList = ref([])
const embeddingList = ref([])
// 默认sizeOption
const showDropdown = ref(false)
const x = ref(0)
const y = ref(0)
const selectModel = ref(null)
const samperOptions = ref([])
const schdulerOptions = ref([])


const isResourceOk = ref(true)
const {imageSizeOption, hrUpscalerOptions,loraSelectModelOption} = stableDiffusionDict()
const formRef = ref(null)
const programmeShow = ref(false)

const rules = {
  defaultModel: {
    required: true,
    message: '请选择模型'
  },
  defaultVae: {
    required: true,
    message: '请选择模型'
  },
  defaultSeed:{
    required: true,
    message: '请输入随机种子'
  },
  defaultSamplerName: {
    required: true,
    message: '请选择采样器'
  },
  defaultBatchSize: {
    required: true,
    message: '请输入批次数量'
  },
  defaultSteps: {
    required: true,
    message: '请输入采样迭代步数'
  },
  defaultWidth:{
    required: true,
    message:'请输入图片尺寸'
  },
  defaultHeight:{
    required: true,
    message:'请输入图片尺寸'
  },
  defaultCfgScale:{
    required: true,
    message: '请输入提示词相关性'
  }
};

const props = defineProps({
  paintEngineConfig: {
    type: Object,
    required: true
  },
  resourceId: {
    type: String,
    required: true
  },
  model:{
    type: String,
    default : 'novel'
  }
})


onMounted(() => {
  getResourceConfig()
})


const getResourceConfig = () => {
  resourceLoading.value = true
  resourceController.getReousceConfig(props.resourceId)
      .then(res => {
        isResourceOk.value = true
        resourceLoading.value = false
        if (res.code === 200) {
          modelOption.value = []
          vaeOption.value = []
          loraList.value = []
          res.data.modelList.forEach((item: any) => {
            // @ts-ignore
            modelOption.value.push({
              label: item.fileName,
              value: item.fileName,
              url: item.modelImage
            })
          })
          res.data.vaeList.forEach((item: any) => {
            // @ts-ignore
            vaeOption.value.push({
              label: item,
              value: item
            })
          })

          res.data.samplerList.forEach((item: any) => {
            // @ts-ignore
            samperOptions.value.push({
              label: item,
              value: item
            })
          })

          res.data.schedulerList.forEach((item: any) => {
            // @ts-ignore
            schdulerOptions.value.push({
              label: item.label,
              value: item.name
            })
          })

          loraList.value = res.data.loraList
          embeddingList.value = res.data.embeddingList
          props.paintEngineConfig.defaultModel = res.data.selectModel
          props.paintEngineConfig.defaultVae = res.data.selectVae
        } else {
          isResourceOk.value = false
        }
      }).catch(()=>{
        isResourceOk.value = false
      }).finally(() => {
        resourceLoading.value = false
      })
}

const changeModel = (value: string) => {
  // resourceController.cha
  const data = {
    resourceId: props.resourceId,
    key: 'sd_model_checkpoint',
    value: value
  }
  changeOption(data)
}

const changeVae = (value: string) => {
  const data = {
    resourceId: props.resourceId,
    key: 'sd_vae',
    value: value
  }
  changeOption(data)
}

const changeOption = (data: any) => {
  resourceLoading.value = true
  resourceController.changeOption(data).then(res => {
    if (res.code != 200) {
      message.error(res.msg);
    }
  }).catch(() => {
    message.error("切换参数失败！")
  }).finally(() => {
    resourceLoading.value = false
  })
}

const setSizeOption = (sizeOption: any) => {
  if (sizeOption === "1") {
    props.paintEngineConfig.defaultWidth = 512
    props.paintEngineConfig.defaultHeight = 512
  } else if (sizeOption === "2") {
    props.paintEngineConfig.defaultWidth = 768
    props.paintEngineConfig.defaultHeight = 512
  } else if (sizeOption === "3") {
    props.paintEngineConfig.defaultWidth = 512
    props.paintEngineConfig.defaultHeight = 768
  } else if (sizeOption === "4") {
    props.paintEngineConfig.defaultWidth = 1024
    props.paintEngineConfig.defaultHeight = 768
  } else if (sizeOption === "5") {
    props.paintEngineConfig.defaultWidth = 768
    props.paintEngineConfig.defaultHeight = 1024
  }
}

const clickOutSide = () => {
  showDropdown.value = false
}


const handleSelect = (key: string | number) => {
  showDropdown.value = false
  if (key === 'addPositive') {
    props.paintEngineConfig.defaultPrompt = props.paintEngineConfig.defaultPrompt + "," + selectModel.value.modelName
  } else if (key === 'addNegative') {
    props.paintEngineConfig.defaultNegativePrompt = props.paintEngineConfig.defaultNegativePrompt + "," + selectModel.value.modelName
  }
}


const handleContextMenu = (type: string, model: any, e: MouseEvent) => {
  e.preventDefault()
  selectModel.value = Object.assign({}, model);
  showDropdown.value = false
  if (type === 'lora') {
    selectModel.value.modelName = '<lora:' + model.modelName + ':1>'
  }
  nextTick().then(() => {
    showDropdown.value = true
    x.value = e.clientX
    y.value = e.clientY
  })
}


const validateForm = (fr:any) =>{
  return new Promise((resolve) => {
    fr.value?.validate((errors) => {
      if(!errors){
        resolve(true)
      }else {
        resolve(false)
      }
    });
  });
}

const validate = async () => {
  return Promise.all([
    validateForm(formRef)
  ]).then(async (results) => {
    const allValid = results.every((valid) => valid)
    return !!allValid;
  })
}

defineExpose({
  validate
})

const choseProgrammeConfig = (programmeConfig:string) =>{
  const config = JSON.parse(programmeConfig)
  props.paintEngineConfig.defaultPrompt = config.defaultPrompt
  props.paintEngineConfig.defaultHeight = config.defaultHeight
  props.paintEngineConfig.defaultWidth = config.defaultWidth
  props.paintEngineConfig.defaultSeed = config.defaultSeed
  props.paintEngineConfig.defaultSamplerName = config.defaultSamplerName
  props.paintEngineConfig.defaultBatchSize = config.defaultBatchSize
  props.paintEngineConfig.defaultSteps = config.defaultSteps
  props.paintEngineConfig.defaultCfgScale = config.defaultCfgScale
  props.paintEngineConfig.defaultRestoreFaces = config.defaultRestoreFaces
  props.paintEngineConfig.defaultEnableHr = config.defaultEnableHr
  props.paintEngineConfig.defaultHrUpscaler = config.defaultHrUpscaler
  props.paintEngineConfig.defaultHrScale = config.defaultHrScale
  props.paintEngineConfig.defaultDenoisingStrength = config.defaultDenoisingStrength
  props.paintEngineConfig.defaultHrSecondPassSteps = config.defaultHrSecondPassSteps
  props.paintEngineConfig.defaultStyleId = config.defaultStyleId
  props.paintEngineConfig.defaultNegativePrompt = config.defaultNegativePrompt
  props.paintEngineConfig.defaultModel = config.defaultModel
  props.paintEngineConfig.defaultVae = config.defaultVae
  props.paintEngineConfig.sizeOption = config.sizeOption
  props.paintEngineConfig.defaultControlNet = config.defaultControlNet
  props.paintEngineConfig.defaultRepaintTimes = config.defaultRepaintTimes
  props.paintEngineConfig.defaultRepaintModel = config.defaultRepaintModel
  props.paintEngineConfig.defaultDynamicThresholding = config.defaultDynamicThresholding
  programmeShow.value = false
  window.$message.success("加载配置成功！")

}
</script>

<style>
.image-container-lora {
  height: 150px; /* 设置容器的固定高度 */
  display: flex; /* 使用Flex布局 */
  align-items: center; /* 垂直居中 */
  justify-content: center; /* 水平居中 */
}

.centered-image-lora {
  max-height: 100%; /* 图片的最大高度为容器高度，宽度会自动适应宽高比例 */
  max-width: 100%; /* 图片的最大宽度为容器宽度，高度会自动适应宽高比例 */
}
</style>
